<template>
  <div class="rx-fixed"  :rx-placement="curPlacement||placement" :class="{active:active}" :style="{
    'min-width':minWidth,
    top:top,
    left:left,
    right:right,
  }">
    <div class="rx-fixed-content rx-arrow-content">
      <div class="rx-arrow hollow"></div>
      <slot></slot>
    </div>
  </div>
</template>
<script>
import {addResize as addWindowResize,addWheelListener,triggerOnce as eventTriggerOnce} from "@rxTools/brower/event";

export default {
  name: "rx-fixed",
  data() {
    return {
      active: false,// 显示隐藏
      minWidth: "auto",//最小宽度，默认和容器等宽
      curPlacement: "",//当前的方位，计算后的
      top: 0,
      left: 0,
      right:0,
    };
  },
  props: {
    placement: "",
    offset: {
      //偏移
      type: Object,
      default() {
        return {
          top: 0,
          left: 0,
          right: 0,
          bottom: 0
        };
      }
    }
  },
  watch: {
    active(val) {
      if (!val) {
        /* 移除事件监听 */
        this.removeWheelEventListener();
        this.removeResizeEventListener();
        this.removeEventTriggerOnce();
        /* 释放内存 */
        this.removeWheelEventListener = null;
        this.removeResizeEventListener = null;
        this.removeEventTriggerOnce = null;
        /* 触发fixed.js 的promise */
        this.$emit("reject");
        this.$emit('onHide');
      } else {
        this.$emit('onShow', this.$el);
      }
    }
  },
  methods: {
    reject() {
      this.active = false;
    }
  },
  mounted() {
    /* 对外事件 start */
    var _this = this;
    /**
     * 隐藏浮层
     */
    this.hide = function() {
      _this.active = false;
    };
    /**
     * 显示浮层
     * @augments triggerEL Element 触发的元素
     * @augments ev Event 时间对象
     */
    this.show = function(triggerEL, ev) {
      if (!_this.active) {
        _this.toggle(triggerEL, ev);
      }
    };
    /**
     * 调戏浮层
     * @augments triggerEL Element 触发的元素
     * @augments ev Event 时间对象
     */
    this.toggle = function(triggerEL, ev) {
      // 判断是否浮层触发
      var contentEl = _this.$el;
      if (contentEl.contains(ev.target)) {
        return;
      }
      //正常触发
      if ( _this.active = !_this.active) {
        //添加resize，mouseWheel，单事件触发
        _this.removeResizeEventListener = addWindowResize(() => {
          _this.active = false;
        });
        _this.removeWheelEventListener = addWheelListener(
          document,
          ev => {
            if (!_this.$el.contains(ev.target)) {
              //不在元素内的滚动，触发active，真的灵泛
              _this.active = false;
            }
          },
          true
        );
        _this.removeEventTriggerOnce = eventTriggerOnce(
          triggerEL,
          () => {
            _this.active = false;
          },
          ev.type
        );

        //计算方位
        var winHeight = window.innerHeight,
          winWidth = window.innerWidth,
          bcr = triggerEL.getBoundingClientRect();

        _this.minWidth = bcr.width + "px";

        Vue.nextTick(() => {
          //计算显示位置
          var contentHeight = contentEl.clientHeight,
            placement = _this.placement.split("-"),
            p1 = placement[0],
            p2 = placement[1],
            pos = {
              top: bcr.top,
              left: bcr.left,
              width: bcr.width,
              height: bcr.height,
              winHeight,
              winWidth,
              contentHeight
            };
          var topPos = calcContentTop(p1, pos),
            leftPos = calcContentLeft(p2, pos);

          _this.curPlacement = topPos.placement + "-" + leftPos.placement;
          if (leftPos && leftPos.left) {//判断是否有left或者right
              this.left = leftPos.left + "px";
              this.right = 'auto'
          } else if (leftPos && leftPos.right) {
              this.right = leftPos.right + "px";
              this.left = 'auto'
          } else{
             this.right ='auto';
              this.left = 'auto';
          }
          _this.top = topPos.top + "px";

          //滚动到active
          var activeEl = _this.$el.querySelector(".is-active");
          activeEl && activeEl.scrollIntoView(false);
        });
      }
    };
    /* 对外事件 end */
  }
};
//位置计算函数
/**
 * 计算top值
 * @augments placement String 方位
 * @augments pos Object 位置对象
 * @augments isReCal Boolean 是否重算，重算就不再重算了,防止死循环
 */
function calcContentTop(placement, pos ,isReCal) {
  switch (placement) {
    case "bottom":
      //trigger高+内容偏移top
      var top = pos.height + pos.top;
      //重算
      if (!isReCal&&top + pos.contentHeight > pos.winHeight) {
        return calcContentTop("top", pos ,true);
      }
      return {
        placement: "bottom",
        top
      };
      break;
    case "top":
      //内容偏移top-content高
      var top = pos.top - pos.contentHeight;
      //重算
      if (!isReCal&&top < 0) {
        return calcContentTop("bottom", pos,true);
      }
      return {
        placement: "top",
        top
      };
      break;
  }
}
function calcContentLeft(placement, pos) {
  switch (placement) {
    case "start":
      var left = pos.left;
      return {
        placement: "start",
        left
      };
      break;
    case "center":
      break;
    case "end":
     var right = $(document).width() - (pos.left + pos.width);
      return {
        placement: "end",
        right
      };
      break;
  }
}
</script>
<style lang="scss">
@import "./arrow.scss";

.rx-fixed {
  position: fixed;
  z-index: 2;
  display: none;

  &.active {
    display: block;
  }
}
</style>
